﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;
using System.Net;
using System.Collections;
using System.Threading;


namespace CaiyinSoft.NetGather.NetGatherUtility
{
    public class Utility
    {

        public static string Encode(string url)
        {
            return Encode(url, 2);
        }

        public static string Encode(string url, int ver)
        {

            //textBox2.Text = SOSORSS.Utility.Encode(textBox1.Text);
            byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(url);

            System.IO.MemoryStream outputFileStream =
                new System.IO.MemoryStream();

            // Create a new ToBase64Transform object to convert to base 64.
            ToBase64Transform base64Transform = new ToBase64Transform();

            // Create a new byte array with the size of the output block size.
            byte[] outputBytes = new byte[base64Transform.OutputBlockSize];


            // Verify that multiple blocks can not be transformed.
            if (!base64Transform.CanTransformMultipleBlocks)
            {
                // Initializie the offset size.
                int inputOffset = 0;

                // Iterate through inputBytes transforming by blockSize.
                int inputBlockSize = base64Transform.InputBlockSize;

                while (inputBytes.Length - inputOffset > inputBlockSize)
                {
                    base64Transform.TransformBlock(
                        inputBytes,
                        inputOffset,
                        inputBytes.Length - inputOffset,
                        outputBytes,
                        0);

                    inputOffset += base64Transform.InputBlockSize;
                    outputFileStream.Write(
                        outputBytes,
                        0,
                        base64Transform.OutputBlockSize);
                }

                // Transform the final block of data.
                outputBytes = base64Transform.TransformFinalBlock(
                    inputBytes,
                    inputOffset,
                    inputBytes.Length - inputOffset);

                outputFileStream.Write(outputBytes, 0, outputBytes.Length);

            }

            // Determine if the current transform can be reused.
            if (!base64Transform.CanReuseTransform)
            {
                // Free up any used resources.
                base64Transform.Clear();
            }

            // Close file streams.

            outputFileStream.Position = 0;
            System.IO.StreamReader sr = new System.IO.StreamReader(outputFileStream);
            string reValue = sr.ReadToEnd();

            outputFileStream.Close();

            string aaa = reValue.Replace("=", "7654321");

            if (ver == 2)
            {
                int weishu = 63;
                string re1 = "";
                string re2 = "";
                int sp1 = aaa.Length / weishu;
                for (int i = 0; i < sp1; i++)
                {
                    re2 = "1";
                    for (int j = 0; j < weishu; j++)
                    {
                        if (char.IsUpper(aaa, j + i * weishu))
                        {
                            re2 += "1";
                        }
                        else
                        {
                            re2 += "0";
                        }
                    }

                    re1 += Convert.ToString(Convert.ToInt64(re2, 2), 16) + "_";
                }

                if (aaa.Length % weishu != 0)
                {
                    re2 = "1";
                    for (int j = sp1 * weishu; j < aaa.Length; j++)
                    {
                        if (char.IsUpper(aaa, j))
                        {
                            re2 += "1";
                        }
                        else
                        {
                            re2 += "0";
                        }
                    }
                    re1 += Convert.ToString(Convert.ToInt64(re2, 2), 16) + "_";
                    sp1++;
                }


                return "v2_" + sp1.ToString() + "_" + re1 + aaa.ToLower();//reValue.Replace("=","7654321");
            }
            else
                return aaa;

        }

        public static string Decode(string url)
        {
            string turl = ""; ;
            if (url.Substring(0, 3).ToLower() == "v2_")
            {
                turl = url.Substring(3);
                string[] splits = turl.Split(new char[] { '_' });
                string re1 = "";
                for (int ui = 0; ui < Convert.ToInt32(splits[0]); ui++)
                {
                    string re2 = Convert.ToString(Convert.ToInt64(splits[ui + 1], 16), 2).Substring(1);
                    re1 += re2;
                }

                string newurl = splits[splits.Length - 1];
                StringBuilder sb = new StringBuilder();
                for (int ui = 0; ui < newurl.Length; ui++)
                {
                    if (re1.Substring(ui, 1) == "0")
                        sb.Append(newurl.Substring(ui, 1).ToLower());
                    else
                        sb.Append(newurl.Substring(ui, 1).ToUpper());
                }

                url = sb.ToString();
            }

            FromBase64Transform myTransform = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces);

            byte[] myOutputBytes = new byte[myTransform.OutputBlockSize];

            //Open the input and output files.
            System.IO.MemoryStream myOutputFile = new System.IO.MemoryStream();

            //Retrieve the file contents into a byte array.
            byte[] myInputBytes = System.Text.Encoding.UTF8.GetBytes(url.Replace("7654321", "="));

            //Transform the data in chunks the size of InputBlockSize.
            int i = 0;
            while (myInputBytes.Length - i > 4/*myTransform.InputBlockSize*/)
            {
                myTransform.TransformBlock(myInputBytes, i, 4/*myTransform.InputBlockSize*/, myOutputBytes, 0);
                i += 4/*myTransform.InputBlockSize*/;
                myOutputFile.Write(myOutputBytes, 0, myTransform.OutputBlockSize);
            }

            //Transform the final block of data.
            myOutputBytes = myTransform.TransformFinalBlock(myInputBytes, i, myInputBytes.Length - i);
            myOutputFile.Write(myOutputBytes, 0, myOutputBytes.Length);

            //Free up any used resources.
            myTransform.Clear();

            myOutputFile.Position = 0;
            System.IO.StreamReader sr = new System.IO.StreamReader(myOutputFile);
            string reValue = sr.ReadToEnd();
            myOutputFile.Close();
            return reValue;

        }

        public static string Encode2(string url)
        {
            string newurl = url.Replace("http://", "$//").Replace(".com", "$m").Replace("soso", "$s");
            StringBuilder sb = new StringBuilder(newurl.Length);
            for (int i = newurl.Length - 1; i >= 0; i--)
            {
                sb.Append(newurl.Substring(i, 1));
            }

            return sb.ToString();
        }

        public static string Decode2(string url)
        {
            StringBuilder sb = new StringBuilder(url.Length);
            for (int i = url.Length - 1; i >= 0; i--)
            {
                sb.Append(url.Substring(i, 1));
            }

            string newurl = sb.ToString();
            newurl = newurl.Replace("$//", "http://").Replace("$m", ".com").Replace("$s", "soso");
            return newurl;
        }

        public static bool IsGUID(string guid)
        {
            string pattern = @"\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b";
            System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(pattern);
            return regex.IsMatch(guid);
        }
    }

    public class WebUtils
    {
        public static string DoWebClientGet(string url, System.Text.Encoding encoding)
        {
            System.Net.WebClient wc = new System.Net.WebClient();
            System.IO.Stream stream = wc.OpenRead(url);
            System.IO.StreamReader sr = new System.IO.StreamReader(stream, encoding);

            string ss = sr.ReadToEnd();
            sr.Close();
            return ss;
        }

        /// <summary>
        /// 执行HTTP POST请求。
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <param name="parameters">请求参数</param>
        /// <returns>HTTP响应</returns>
        public static string DoGet(string url, System.Text.Encoding encoding)
        {
            return DoWebRequest("GET", url, encoding, "");
        }


        /// <summary>
        /// 执行HTTP POST请求。
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <param name="parameters">请求参数</param>
        /// <returns>HTTP响应</returns>
        public static string DoPost(string url, System.Text.Encoding encoding)
        {
            return DoWebRequest("POST", url, encoding, "");
        }

        public static string DoWebRequest(string method,string url, System.Text.Encoding encoding, string para)
        {

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = method;// "POST";
            req.KeepAlive = true;
            req.UserAgent = "Mozilla/5.0+(Windows;+U;+Windows+NT+5.1;+en-US)+AppleWebKit/534.3+(KHTML,+like+Gecko)+Chrome/6.0.472.62+Safari/534.3";
            req.ContentType = "application/x-www-form-urlencoded;charset=utf-8";

            if (para.Length > 0 && method.CompareTo("POST") == 0)
            {
                string postdata = para;//.Replace("?","^^").Replace("&","**");
                //string turl = url + "?" + postdata;
                byte[] postData = Encoding.UTF8.GetBytes(postdata);
                Stream reqStream = req.GetRequestStream();
                reqStream.Write(postData, 0, postData.Length);
                reqStream.Close();
            }

            HttpWebResponse rsp = (HttpWebResponse)req.GetResponse();
            //Encoding encoding = Encoding.GetEncoding(rsp.CharacterSet);
            return GetResponseAsString(rsp, encoding);


        }

        /// <summary>
        /// 把响应流转换为文本。
        /// </summary>
        /// <param name="rsp">响应流对象</param>
        /// <param name="encoding">编码方式</param>
        /// <returns>响应文本</returns>
        private static string GetResponseAsString(HttpWebResponse rsp, Encoding encoding)
        {
            StringBuilder result = new StringBuilder();
            Stream stream = null;
            StreamReader reader = null;

            try
            {

                // 以字符流的方式读取HTTP响应
                stream = rsp.GetResponseStream();
                reader = new StreamReader(stream, encoding);

                // 每次读取不大于512个字符，并写入字符串
                char[] buffer = new char[512];
                int readBytes = 0;
                while ((readBytes = reader.Read(buffer, 0, buffer.Length)) > 0)
                {
                    result.Append(buffer, 0, readBytes);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                // 释放资源
                if (reader != null) reader.Close();
                if (stream != null) stream.Close();
                if (rsp != null) rsp.Close();
            }

            return result.ToString();
        }

    }

    public class LinkUrl
    {
        public string url { get; set; }
        public DateTime lastVisitTime { get; set; }

        public LinkUrl(string url)
        {
            this.url = url;
            this.lastVisitTime = DateTime.Now;
        }
    }

    public class HTMLGather
    {
        private static int LastVisitUrlIndex = 0;
        static List<LinkUrl> linkUrls;
        static HTMLGather()
        {
            LastVisitUrlIndex = 0;
            linkUrls = new List<LinkUrl>();
            linkUrls.Add(new LinkUrl(""));
        }

        public static void AddUrl(string GetXMLUrl)
        {
            linkUrls.Add(new LinkUrl(GetXMLUrl));
        }

        public static string GetHTML(string url)
        {
            return GetHTML(url, System.Text.Encoding.UTF8);
        }

        public static string GetHTML(string url, string encoding)
        {
            return GetHTML(url, System.Text.Encoding.GetEncoding(encoding));
        }

        public static string GetHTML(string url, System.Text.Encoding encoding)
        {
            string xml = "";
            Interlocked.Increment(ref LastVisitUrlIndex);  //标记+1
            {
                int realIndex = LastVisitUrlIndex;
                if (realIndex >= linkUrls.Count)
                {
                    realIndex = 0;
                }
                if (encoding != System.Text.Encoding.UTF8)
                    realIndex = 0;

                TimeSpan span = DateTime.Now - linkUrls[realIndex].lastVisitTime;
                if (span.Milliseconds < 800)
                {
                    System.Threading.Thread.Sleep(span.Milliseconds + 100);
                }

                if (linkUrls[realIndex].url.Length == 0)
                {
                    xml = WebUtils.DoGet(url, encoding);
                }
                else
                {
                    xml = WebUtils.DoWebClientGet(linkUrls[realIndex].url, encoding);
                }

                linkUrls[realIndex].lastVisitTime = DateTime.Now;

                LastVisitUrlIndex++;
                if (LastVisitUrlIndex >= linkUrls.Count)
                    LastVisitUrlIndex = 0;
            }
            Interlocked.Decrement(ref LastVisitUrlIndex);
            return xml;
        }
    }

    public class HTMLProcess
    {
        public static void RemoveA(HtmlAgilityPack.HtmlNode parentNode)
        {
            foreach (HtmlAgilityPack.HtmlNode link in parentNode.ChildNodes)
            {
                foreach (HtmlAgilityPack.HtmlNode a in link.Elements("a"))
                {
                    if (a.Attributes["href"] != null)
                        a.Attributes["href"].Remove();
                }

                System.Collections.Generic.IEnumerable<HtmlAgilityPack.HtmlNode> scripts = link.Elements("script");
                foreach (HtmlAgilityPack.HtmlNode script in scripts)
                {
                    script.RemoveAll();
                }


                RemoveA(link);
            }
        }
    }

    public class UriParser
    {
        public static bool IsTextUTF8(ref byte[] inputStream)
        {

            int encodingBytesCount = 0;

            bool allTextsAreASCIIChars = true;



            for (int i = 0; i < inputStream.Length; i++)
            {

                byte current = inputStream[i];



                if ((current & 0x80) == 0x80)
                {

                    allTextsAreASCIIChars = false;

                }

                // First byte

                if (encodingBytesCount == 0)
                {

                    if ((current & 0x80) == 0)
                    {

                        // ASCII chars, from 0x00-0x7F

                        continue;

                    }



                    if ((current & 0xC0) == 0xC0)
                    {

                        encodingBytesCount = 1;

                        current <<= 2;



                        // More than two bytes used to encoding a unicode char.

                        // Calculate the real length.

                        while ((current & 0x80) == 0x80)
                        {

                            current <<= 1;

                            encodingBytesCount++;

                        }

                    }

                    else
                    {

                        // Invalid bits structure for UTF8 encoding rule.

                        return false;

                    }

                }

                else
                {

                    // Following bytes, must start with 10.

                    if ((current & 0xC0) == 0x80)
                    {

                        encodingBytesCount--;

                    }

                    else
                    {

                        // Invalid bits structure for UTF8 encoding rule.

                        return false;

                    }

                }

            }



            if (encodingBytesCount != 0)
            {

                // Invalid bits structure for UTF8 encoding rule.

                // Wrong following bytes count.

                return false;

            }



            // Although UTF8 supports encoding for ASCII chars, we regard as a input stream, whose contents are all ASCII as default encoding.

            return !allTextsAreASCIIChars;

        }
    }

    public class Taobao
    {

        /// <summary>
        /// 去掉所有标点符号以后的字符串
        /// </summary>
        /// <param name="oldTitle"></param>
        /// <returns></returns>
        public static string RemoveAllMark(string oldTitle)
        {

            HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(oldTitle);
            string str = doc.DocumentNode.InnerText;

            System.Text.RegularExpressions.Regex reg= new System.Text.RegularExpressions.Regex(@"[^\w|\s|\-|\+|\u4e00-\u9fa5]");
            str = reg.Replace(str, " ");

            System.Text.RegularExpressions.Regex reg1 = new System.Text.RegularExpressions.Regex(@"\-+");
            str = reg1.Replace(str, "-");

            System.Text.RegularExpressions.Regex reg3 = new System.Text.RegularExpressions.Regex(@"\++");
            str = reg3.Replace(str, "+");

            System.Text.RegularExpressions.Regex reg4 = new System.Text.RegularExpressions.Regex(@"\|");
            str = reg4.Replace(str, " ");

           System.Text.RegularExpressions.Regex regN = new System.Text.RegularExpressions.Regex(@"\s+");
            str = regN.Replace(str, " ");


            return str;
        }

        public static string[] RemoveAllMarkArray(string oldTitle)
        {
            string str = RemoveAllMark(oldTitle);
            string[] strs= str.Trim().Split(new char[] { ' ' });
            
            return strs;
        }

        /// <summary>
        /// 取到标点后，对数组倒序，然后连接成字符
        /// </summary>
        /// <param name="Title"></param>
        /// <returns></returns>
        public static string getNewTitle(string oldTitle)
        {
            return getNewTitle(oldTitle, "/");
        }

        public static string getNewTitle(string oldTitle,string Spe)
        {
            string[] strs = RemoveAllMarkArray(oldTitle);

            //Array.Sort(strs);
            Array.Reverse(strs);

            StringBuilder sb = new StringBuilder();
            foreach (string str in strs)
            {
                if (sb.Length > 0)
                    sb.Append(Spe + str);
                else
                    sb.Append(str);

            }

            return sb.ToString();
        }

        /// <summary>
        /// 取到标点后，从前往后连接字符数组
        /// </summary>
        /// <param name="Title"></param>
        /// <returns></returns>
        public static string getMateKeyword(string Title)
        {
            return getMateKeyword(Title, ",");
        }
        public static string getMateKeyword(string Title, string Spe)
        {
            string[] strs = RemoveAllMarkArray(Title);
            StringBuilder sb = new StringBuilder();
            foreach (string str in strs)
            {
                if (sb.Length > 0)
                    sb.Append(Spe + str);
                else
                    sb.Append(str);
            }

            return sb.ToString();
        }
    }
}
